package com.jumper.mydemo.statics;

import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.jumper.mydemo.my.MyBeanPostProcessor;
import com.jumper.mydemo.my.MyConfiguration;
import com.jumper.mydemo.my.MyRepository;
import com.jumper.mydemo.my.MyServiceA;

public class AutowireCapableBeanFactoryDemo {
    @SuppressWarnings("resource")
    public static void run() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfiguration.class);

        applicationContext.getBeanFactory().addBeanPostProcessor(new MyBeanPostProcessor());
        applicationContext.getBeanFactory().registerSingleton("myRepository", new MyRepository());
        
        AutowireCapableBeanFactory beanFactory = applicationContext.getAutowireCapableBeanFactory();
        resolveDependency(beanFactory);
    }

    private static void createBean(AutowireCapableBeanFactory beanFactory) {
        Object object = beanFactory.getBean("myRepository");
        System.out.println("MyRepository object:" + object);
        MyServiceA myServiceA = beanFactory.createBean(MyServiceA.class);
        System.out.println("调用crateBean方法创建对象:" + myServiceA);
    }

    private static void configureBean(AutowireCapableBeanFactory beanFactory) {
        ((DefaultListableBeanFactory) beanFactory).registerBeanDefinition("myServiceA", new RootBeanDefinition(MyServiceA.class));
        
        MyServiceA myService = new MyServiceA();
        System.out.println("调用configureBean前,MyService = " + myService);
        beanFactory.configureBean(myService, "myServiceA");
        System.out.println("调用configureBean后, MyService = " + myService);
    }

    private static void autowireBean(AutowireCapableBeanFactory beanFactory) {
        MyServiceA myService = new MyServiceA();
        System.out.println("调用autowireBean前, MyService = " + myService);
        beanFactory.autowireBean(myService);
        System.out.println("调用autowireBean后, MyService = " + myService);
    }

    private static void autowire(AutowireCapableBeanFactory beanFactory) {
        Object myService = beanFactory.autowire(MyServiceA.class, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false);
        System.out.println("调用autowire方法, 创建Bean对象:" + myService);
    }

    private static void autowireBeanProperties(AutowireCapableBeanFactory beanFactory) {
        MyServiceA myService = new MyServiceA();
        System.out.println("调用autowireBeanProperties前, myService = " + myService);
        beanFactory.autowireBeanProperties(myService, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false);
        System.out.println("调用autowireBeanProperties后，myService = " + myService);
    }

    private static void applyBeanPropertyValues(AutowireCapableBeanFactory beanFactory) {
        PropertyValue propertyValue = new PropertyValue("javaHome", "This is my custom javaHome");
        MutablePropertyValues propertyValues = new MutablePropertyValues();
        propertyValues.addPropertyValue(propertyValue);

        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(MyServiceA.class);
        rootBeanDefinition.setPropertyValues(propertyValues);
        ((DefaultListableBeanFactory) beanFactory).registerBeanDefinition("myServiceA", rootBeanDefinition);

        MyServiceA myServiceA = new MyServiceA();
        System.out.println("调用applyBeanPropertyValues前, myServiceA = " + myServiceA);
        beanFactory.applyBeanPropertyValues(myServiceA, "myServiceA");
        System.out.println("调用applyBeanPropertyValues后, myServiceA = " + myServiceA);
    }

    private static void initializeBean(AutowireCapableBeanFactory beanFactory) {
        MyServiceA myService = new MyServiceA();
        System.out.println("调用initializeBean前, myService = " + myService);
        beanFactory.initializeBean(myService, "myServiceA");
        System.out.println("调用initilizeBean后, myService = " + myService);
    }

    private static void destroyBean(AutowireCapableBeanFactory beanFactory) {
        beanFactory.destroyBean(new MyServiceA());
    }

    private static void resolveDependency(AutowireCapableBeanFactory beanFactory) {
        try {
            DependencyDescriptor dependencyDescriptor = new DependencyDescriptor(MyServiceA.class.getDeclaredField("myRepository"), false);
            Object resolveDependency = beanFactory.resolveDependency(dependencyDescriptor, "myRepository");
            System.out.println("resolveDependency = " + resolveDependency);
        } catch(NoSuchFieldException e) {
            e.printStackTrace();
        }
    }
}
